// 其他 AudioContext API 移步 https://developer.mozilla.org/zh-CN/docs/Web/API/AudioContext
function Musicvisualizer(obj) {
  this.source = null;
  this.count = 0;
  this.musicConf = obj.musicConf || {volume: 1};

  // 分析器
  this.analyser = Musicvisualizer.ac.createAnalyser();
  this.size = obj.size;
  this.analyser.fftSize = this.size * 2;
  // 目标设备 将数据导入到 destination 中播放， 中间可以连接多个其他“设备”
  // 注意 connect 方法 第一个参数是设备， 第二个是输出（插头）， 第三个是输入（插孔）
  // 比如 splitter.connect(this.gainNodeL, 0, 0); 可以理解为 将左声道控制器的第一个插头 插入声道拆分器的第一个插孔，第二三个参数的默认值为 0；
  // 如果找不到插孔和插槽将报错，但是符合规则的连接将不会报错， 但是可能不是想要的效果。
  const destination = Musicvisualizer.ac.destination;
  // GainNode用来控制音频的音量
  // 总音量
  this.gainNode = Musicvisualizer.ac[Musicvisualizer.ac.createGain ? "createGain" : "createGainNode"]();
  // 左右声道
  this.gainNodeL = Musicvisualizer.ac[Musicvisualizer.ac.createGain ? "createGain" : "createGainNode"]();
  this.gainNodeR = Musicvisualizer.ac[Musicvisualizer.ac.createGain ? "createGain" : "createGainNode"]();
  // 声道拆分器
  const splitter = Musicvisualizer.ac.createChannelSplitter(2);
  // 声道合成器
  const merger = Musicvisualizer.ac.createChannelMerger(2);

  // 左声道音量
  this.gainNodeL.gain.value = 1;
  // 右声道音量
  this.gainNodeR.gain.value = 1;
  // 总音量
  this.gainNode.gain.value = 1;

  // 连接设备到总音量
  this.gainNode.connect(destination);
  // 连接总音量到合并转接口
  merger.connect(this.gainNode);
  // 连接转接口到声道音量控制
  this.gainNodeL.connect(merger, 0, 0);
  this.gainNodeR.connect(merger, 0, 1);
  // 连接声道音量控制到拆分转接口
  splitter.connect(this.gainNodeL, 0, 0);
  splitter.connect(this.gainNodeR, 1, 0);
  // 连接拆分转接口到波谱分析器 // 最终波谱分析器会连接到音频数据
  this.analyser.connect(splitter);

  // ajax
  this.xhr = new XMLHttpRequest();
  // 绘制播放动画的方法由外界导入
  this.draw = obj.draw;

  // 开始绘制
  this.visualize();
}

// 音频上下文
Musicvisualizer.ac = new (window.AudioContext || window.webkitAudioContext)();//共用的
// 解决 Chrome 66之后高版本中AudioContext被强行suspend的问题
if (typeof AudioContext !== "undefined" || typeof webkitAudioContext !== "undefined") {
  const resumeAudio = function () {
    if (typeof Musicvisualizer.ac === "undefined" || Musicvisualizer.ac == null) return;
    if (Musicvisualizer.ac.state === "suspended") Musicvisualizer.ac.resume();
    document.removeEventListener("click", resumeAudio);
  };
  document.addEventListener("click", resumeAudio);
}
// load -> decode -> play
Musicvisualizer.prototype.load = function (url, fun) {
  this.xhr.abort();
  this.xhr.open("GET", url);
  this.xhr.responseType = "arraybuffer";
  const self = this;
  this.xhr.onload = function () {
    fun(self.xhr.response);
  };
  this.xhr.send();
};

// BaseAudioContext.decodeAudioData()用来生成AudioBuffer
// AudioBuffer供AudioBufferSourceNode使用，这样，AudioBufferSourceNode才可以播放音频数据
Musicvisualizer.prototype.decode = function (arraybuffer, fun) {
  Musicvisualizer.ac.decodeAudioData(arraybuffer, function (buffer) {
    fun(buffer);
  }, function (err) {
    console.log(err);
  });
};

Musicvisualizer.prototype.play = function (path) {
  const n = ++this.count;
  const self = this;
  self.source && self.source[self.source.stop ? "stop" : "noteOff"](); // 开始前先暂停之前音频的播放，防止多份音频同时播放
  if (path instanceof ArrayBuffer) {
    self.decode(path, function (buffer) {
      if (n != self.count) return;
      const bufferSource = Musicvisualizer.ac.createBufferSource();
      // 将解码成功后的buffer赋值给bufferSource的buffer属性
      bufferSource.buffer = buffer;
      // bufferSource.loop = true;
      bufferSource.connect(self.analyser);
      bufferSource[bufferSource.start ? "start" : "noteOn"](0);
      self.source = bufferSource;
    });
  }
  else {
    self.load(path, function (arraybuffer) {
      if (n !== self.count) return;
      self.decode(arraybuffer, function (buffer) {
        if (n !== self.count) return;
        const bufferSource = Musicvisualizer.ac.createBufferSource();
        bufferSource.buffer = buffer;
        bufferSource.connect(self.analyser);
        bufferSource[bufferSource.start ? "start" : "noteOn"](0);
        self.source = bufferSource;
        bufferSource.onended = function(){
          self.musicConf.ended && self.musicConf.ended();
        };
      });
    });
  }
};
// 主音量控制方法
Musicvisualizer.prototype.changeVolumn = function (percent) {
  this.musicConf.volume = this.gainNode.gain.value = percent;
};
// 左右声道控制方法
Musicvisualizer.prototype.setVolumn = function () {
  const {x, y, w, h} = mousemoveConf;
  const ry = (x - w / 2) / w;
  const rx = Math.abs((y - h / 2) / w);
  this.gainNodeL.gain.value = (1 - rx - ry) * (1 - rx - ry);
  this.gainNodeR.gain.value = (1 - rx + ry) * (1 - rx + ry);
};
Musicvisualizer.prototype.visualize = function () {
  const self = this;
  const arr = new Uint8Array(self.analyser.frequencyBinCount);//数组长度是fftsize的一半
  requestAnimationFrame = window.requestAnimationFrame ||
    window.webkitrequestAnimationFrame ||
    window.mozrequestAnimationFrame;//兼容
  function fn() {
    self.analyser.getByteFrequencyData(arr);// 将音频频域数据复制到传入的Uint8Array数组
    self.draw(arr);
    self.changeVolumn(self.musicConf.volume);
    requestAnimationFrame(fn);
  }
  requestAnimationFrame(fn);
}

module.exports = Musicvisualizer;
